热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

实线|都会_[网络基础知识]TCP有限状态机

篇首语:本文由编程笔记#小编为大家整理,主要介绍了[网络基础知识]TCP有限状态机相关的知识,希望对你有一定的参考价值。TCP是传输层协议,实

篇首语:本文由编程笔记#小编为大家整理,主要介绍了[网络基础知识]TCP有限状态机相关的知识,希望对你有一定的参考价值。


TCP是传输层协议,实现了一种可靠的通信。它从不同角度提供了多种可靠性保障措施来为网络传输提供确定性。连接性就是其中之一,不像UDP的无连接状态,TCP在数据传输之前会进行连接,只有双方都协调完成后,才会进行数据传输;同样的,在结束时,又会断开连接,通告传输的完成;在数据传输过程中,又会对每个传输进行确认。



  1. 粗实箭头表示客户进程的正常迁移
  2. 粗虚线箭头表示对服务器进程的正常迁移
  3. 细线箭头表示异常变迁

TCP 协议的操作可以使用一个具有11 种状态的有限状态机( Finite State Machine )来表示。图中用粗线表示客户端主动和被动的服务器端建立连接的正常过程:客户端的状态变迁用粗实线,服务器端的状态变迁用粗虚线。细线用于不常见的序列,如 复位、同时打开、同时关闭等。图中的每条状态变换线上均标有“事件/动作”:事件是指用户执行了系统调用( CONNECT 、 LISTEN 、 SEND 或 CLOSE )、收到一个报文段( SYN 、 FIN 、 ACK 或 RST )、或者是出现了超过两倍最大的分组生命期的情况;动作是指发送一个报文段( SYN 、 FIN 或 ACK )或什么也没有(用“-”表示)。
每个连接均开始于CLOSED 状态。当一方执行了被动的连接原语( LISTEN )或主动的连接原语( CONNECT )时,它便会脱离 CLOSED 状态。如果此时另一方执行了相对应的连接原语,连接便建立了,并且状态变为 ESTABLISHED 。任何一方均可以首先请求释放连接,当连接被释放后,状态又回到了CLOSED 。


11 种有限状态机




CLOSED:关闭状态,没有连接活动或正在进行
LISTEN:监听状态,服务器正在等待连接进入
SYN RCVD:收到一个连接请求,尚未确认
SYN SENT:已经发出连接请求,等待确认
ESTABLISHED:连接建立,正常数据传输状态
FIN WAIT 1:(主动关闭)已经发送关闭请求,等待确认
FIN WAIT 2:(主动关闭)收到对方关闭确认,等待对方关闭请求
TIMED WAIT:完成双向关闭,等待所有分组死掉
CLOSING:双方同时尝试关闭,等待对方确认
CLOSE WAIT:(被动关闭)收到对方关闭请求,已经确认
LAST ACK:(被动关闭)等待最后一个关闭确认,并等待所有分组死掉

常见的问题


网络服务经常出现连接数不够的问题,用netstat -an来定位,统计所有tcp状态的个数。

大量SYN_RCVD 

如果服务器上出现大量的SYN_RCVD状态的TCP连接说明这些连接一直没有收到ACK包,这主要有两种可能,一种是对方(请求方或客户端)没有收到服务器发送的[SYN,ACK]包,另一种可能是对方收到了[SYN,ACK]包却没有ACK。


对于第一种情况一般是由于网络结构或安全规则限制导致(SYN,ACK)包无法发送到对方,这种情况比较容易判断:只要在服务器上能够ping通互联网的任意主机,基本可以排除这种情况。
对于第二种情况要稍微复杂一些,这种情况还有两种可能:一种是对方根本就不打算ACK,一般在对方程序有意为之才会出现,如SYN Flood类型的DOS/DDOS 攻击;另一种可能是对方收到的[SYN,ACK]包不合法,常见的是SYN包的目的地址(服务地址)和应答[SYN,ACK]包的源地址不同。这种情况在只配置了DNAT而不进行SNAT的服务网络环境下容易出现,主要是由于inbound(SYN包)和outbound([SYN,ACK]包)的包穿越了不同的网关/防火墙/负载均衡器,从而导致[SYN,ACK]路由到互联网的源地址(一般是防火墙的出口地址)与SYN包的目的地址(服务的虚拟IP) 不同,这时客户机无法将SYN包和[SYN,ACK]包关联在一起,从而会认为已发出的SYN包还没有被应答,于是继续等待应答包。这样服务器端的连接一直保持在SYN_RCVD状态(半开连接)直到超时。

大量close_wait


在被动关闭连接情况下,在已经接收到FIN,但是还没有发送自己的FIN的时刻,连接处于CLOSE_WAIT状态。
通常来讲,CLOSE_WAIT状态的持续时间应该很短,正如SYN_RCVD状态。但是在一些特殊情况下,就会出现连接长时间处于CLOSE_WAIT状态的情况。
出现大量close_wait的现象,主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。代码需要判断socket,一旦读到0,断开连接,read返回负,检查一下errno,如果不是AGAIN,就断开连接。
解决方法,基本的思想就是要检测出对方已经关闭的socket,然后关闭它。

  1. 代码需要判断socket,一旦read返回0,断开连接,read返回负,检查一下errno,如果不是AGAIN,也断开连接。(注:在UNP 7.5节的图7.6中,可以看到使用select能够检测出对方发送了FIN,再根据这条规则就可以处理CLOSE_WAIT的连接)
  2. 给每一个socket设置一个时间戳last_update,每接收或者是发送成功数据,就用当前时间更新这个时间戳。定期检查所有的时间戳,如果时间戳与当前时间差值超过一定的阈值,就关闭这个socket。
  3. 使用一个Heart-Beat线程,定期向socket发送指定格式的心跳数据包,如果接收到对方的RST报文,说明对方已经关闭了socket,那么我们也关闭这个socket。
  4. 设置SO_KEEPALIVE选项,并修改内核参数

大量last_ack


大量ack主要是服务器等待客户端主动关闭,而客户端没有及时发出最后一个ack,或者在传输过程中丢包了,可以减少keepalive时间,利用keepalive来关闭这些连接。
调整参数:
# 当keepalive打开的情况下,TCP发送keepalive消息的频率。(默认值是7200(2小时),服务器建议设为1800)
net.ipv4.tcp_keepalive_time = 1800
# 在近端丢弃TCP连接之前﹐要进行多少次重试。默认值是7个﹐在大负载服务器上建议调整为3)
net.ipv4.tcp_orphan_retries = 3

大量TIME_waited


TIME_WAIT产生原因:
主要有两个原因:防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失) 可靠的关闭TCP连接,在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。
一般都是客户端主动关闭连接,服务器被动关闭连接,被动关闭连接时不存在time_wait。但是新增了一些其他需求,比如nginx的负载均衡功能,导致服务器本身也成为一个客户端(比如访问php服务器),在短链接情况下,会更频繁地关闭主动关闭连接,导致系统预留大量的timewait状态的socket。服务器申请不到新的socket导致的,客户不能正常访问服务器。
一个通用比较通用的解决办法:
net.ipv4.tcp_synCOOKIEs = 1 表示开启SYN COOKIEs。当出现SYN等待队列溢出时,启用COOKIEs来处理,可防范少量
SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 (www.111cn.net)表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
net.ipv4.tcp_max_tw_buckets = 5000 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。
默  认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
 
从解决问题的思路, 服务器常见的socket不够问题(除established),其他问题一般都可以通过定时监控来提前发现问题,及时修改系统参数来解决问题。或者增加一套,根据系统剩下的socket资源情况来调整tcp参数,快速规避问题。

TCP有限状态机


推荐阅读
  • 小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限
    小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限 ... [详细]
  • 2016-2017学年《网络安全实战》第三次作业
    2016-2017学年《网络安全实战》第三次作业总结了教材中关于网络信息收集技术的内容。本章主要探讨了网络踩点、网络扫描和网络查点三个关键步骤。其中,网络踩点旨在通过公开渠道收集目标信息,为后续的安全测试奠定基础,而不涉及实际的入侵行为。 ... [详细]
  • Nacos 0.3 数据持久化详解与实践
    本文详细介绍了如何将 Nacos 0.3 的数据持久化到 MySQL 数据库,并提供了具体的步骤和注意事项。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 该大学网站采用PHP和MySQL技术,在校内可免费访问某些外部收费资料数据库。为了方便学生校外访问,建议通过学校账号登录实现免费访问。具体方案可包括利用学校服务器作为代理,结合身份验证机制,确保合法用户在校外也能享受免费资源。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 利用 Python Socket 实现 ICMP 协议下的网络通信
    在计算机网络课程的2.1实验中,学生需要通过Python Socket编程实现一种基于ICMP协议的网络通信功能。与操作系统自带的Ping命令类似,该实验要求学生开发一个简化的、非标准的ICMP通信程序,以加深对ICMP协议及其在网络通信中的应用的理解。通过这一实验,学生将掌握如何使用Python Socket库来构建和解析ICMP数据包,并实现基本的网络探测功能。 ... [详细]
  • Amoeba 通过优化 MySQL 的读写分离功能显著提升了数据库性能。作为一款基于 MySQL 协议的代理工具,Amoeba 能够高效地处理应用程序的请求,并根据预设的规则将 SQL 请求智能地分配到不同的数据库实例,从而实现负载均衡和高可用性。该方案不仅提高了系统的并发处理能力,还有效减少了主数据库的负担,确保了数据的一致性和可靠性。 ... [详细]
  • 在JavaWeb项目架构中,NFS(网络文件系统)的实现与优化是关键环节。NFS允许不同主机系统通过局域网共享文件和目录,提高资源利用率和数据访问效率。本文详细探讨了NFS在JavaWeb项目中的应用,包括配置、性能优化及常见问题的解决方案,旨在为开发者提供实用的技术参考。 ... [详细]
  • Nginx不仅是一款轻量级的高性能Web服务器,还具备出色的负载均衡和反向代理功能。它支持复杂的正则匹配规则、动静内容分离以及灵活的URL重写功能,使得配置和管理更加便捷高效。此外,Nginx提供了多种负载均衡算法,如轮询、加权轮询、最少连接数等,以满足不同应用场景的需求。 ... [详细]
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 西北工业大学作为陕西省三所985和211高校之一,虽然在农业和林业领域不如某些顶尖院校,但在航空航天领域的实力尤为突出。该校的计算机科学专业在科研和教学方面也具有显著优势,是考研的理想选择。 ... [详细]
  • RocketMQ在秒杀时的应用
    目录一、RocketMQ是什么二、broker和nameserver2.1Broker2.2NameServer三、MQ在秒杀场景下的应用3.1利用MQ进行异步操作3. ... [详细]
  • PTArchiver工作原理详解与应用分析
    PTArchiver工作原理及其应用分析本文详细解析了PTArchiver的工作机制,探讨了其在数据归档和管理中的应用。PTArchiver通过高效的压缩算法和灵活的存储策略,实现了对大规模数据的高效管理和长期保存。文章还介绍了其在企业级数据备份、历史数据迁移等场景中的实际应用案例,为用户提供了实用的操作建议和技术支持。 ... [详细]
  • Keepalived 提供了多种强大且灵活的后端健康检查机制,包括 HTTP_GET、SSL_GET、TCP_CHECK、SMTP_CHECK 和 MISC_CHECK 等多种检测方法。这些健康检查功能确保了高可用性环境中的服务稳定性和可靠性。通过合理配置这些检查方式,可以有效监测后端服务器的状态,及时发现并处理故障,从而提高系统的整体性能和可用性。 ... [详细]
author-avatar
IQBB_LongGang
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有